TriggerInfo
triggerInfo = new TriggerInfo();
triggerInfo.EnableTagEventReport
= true;
triggerInfo.TagEventReportInfo.ReportNewTagEvent
= TAG_EVENT_REPORT_TRIGGER.MODERATED;
triggerInfo.TagEventReportInfo.ReportTagInvisibleEvent
= TAG_EVENT_REPORT_TRIGGER.MODERATED;
triggerInfo.TagEventReportInfo.ReportTagBackToVisibilityEvent
= TAG_EVENT_REPORT_TRIGGER.MODERATED;
triggerInfo.TagEventReportInfo.NewTagEventModeratedTimeoutMilliseconds
= 100;
triggerInfo.TagEventReportInfo.TagInvisibleEventModeratedTimeoutMilliseconds
= 100;
triggerInfo.TagEventReportInfo.TagBackToVisibilityModeratedTimeoutMilliseconds
= 100;
rfid3.Actions.Inventory.Perform(null,
triggerInfo, null);
Pre-filters are same as the Select command of C1G2 specification. Once applied, pre-filters are applied prior to Inventory and Access operations.
Singulation refers to the method of identifying an individual Tag in a multiple-Tag environment. RFID Readers could support State-Aware or State-Unaware pre-filtering (or singulation) which is indicated by the boolean flag IsTagInventoryStateAwareSingulationSupported in the ReaderCapabilities class.
In order to filter tags that match a specific condition, it is necessary to use the tag-sessions and their states (setting the tags to different states based on match criteria- rfid3.Actions.PreFilters.Add) so that while performing inventory, tags can be instructed to participate (singulation - rfid3.Config.Antennas[1].SetSingulationControl) or not participate in the inventory based on their states.
Tags provide 4 sessions (denoted S0, S1, S2, and S3) and maintain an independent inventoried flag for each session. Each of the four inventoried flags has two values, denoted A and B. These inventoried flag of each session can be set to A or B based on match criteria using method rfid3.Actions.PreFilters.Add.
Tags provide a selected flag, SL, which can be asserted or deasserted based on match criteria using method rfid3.Actions.PreFilters.Add
In state-unaware singulation the Reader permits 6 options (as enumerated by STATE_UNAWARE_ACTION) of filtering tags. This is more simplified than state-aware singulation.
In state-aware singulation the Application can specify detailed controls for singulation: Action and Target.
Action indicates whether matching Tags assert or deassert SL (Selected Flag), or set their inventoried flag to A or to B. Tags conforming to the match criteria specified using the method rfid3.Actions.PreFilters.Add are considered matching and the remaining are non-matching.
Target indicates whether to modify a Tags SL flag or its inventoried flag, and in the case of inventoried it further specifies one of four sessions.
Truncate action specifies whether a Tag backscatters its entire EPC, or only that portion of the EPC immediately following Mask. During truncated replies a Tag substitutes 00000 for the PC bits. Truncated replies are always followed by the CRC-16 in EPC memory 00h to 0Fh; a Tag does not re compute this CRC for a truncated reply.
The following are the steps to use pre-filters:
Each RFID Reader supports a maximum number of Pre-Filters per Antenna as indicated by rfid3.ReaderCapabilites.MaxNumPreFilters property which can be known using the ReaderCapabilities.
The application can set pre-filters using rfid3.Actions.PreFilters.Add and remove using rfid3.Actions.PreFilters.Delete.
// Add state unaware pre-filter
PreFilters.PreFilter filter = new PreFilters.PreFilter();
byte[] tagMask = new byte[2] { 0x12, 0x11 };
filter.AntennaID = 3;// Set this filter for Antenna ID 3
filter.TagPattern = tagMask;// Tags which starts with 0x1211
filter.TagPatternBitCount = (uint)tagMask.Length * 8;
filter.BitOffset = 32; // skip PC bits (always it should be in bit length)
filter.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;
filter.FilterAction = FILTER_ACTION.FILTER_ACTION_STATE_UNAWARE; // use state unaware singulation
filter.StateUnawareAction.Action = STATE_UNAWARE_ACTION.STATE_UNAWARE_ACTION_UNSELECT; // do not select the tags that match the pre-filter criteria
rfid3.Actions.PreFilters.Add(filter);
// Add state aware pre-filter
PreFilters.PreFilter filter = new PreFilters.PreFilter();
byte[] tagMask = new byte[2] { 0x12, 0x11 };
filter.AntennaID = 3;// Set this filter for Antenna ID 3
filter.TagPattern = tagMask;// Tags which starts with 0x1211
filter.TagPatternBitCount = (uint)tagMask.Length * 8;
filter.BitOffset = 32; // skip PC bits (always it should be in bit length)
filter.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;
filter.FilterAction = FILTER_ACTIONFILTER_ACTION.FILTER_ACTION_STATE_AWARE; // use state aware singulation
filter.StateAwareAction.Target = TARGET.TARGET_INVENTORIED_STATE_S1; // inventoried flag of session S1 of matching tags to B
filter.StateAwareAction.Action = STATE_AWARE_ACTION.STATE_AWARE_ACTION_INV_B; // not to select tags that match the criteria
rfid3.Actions.PreFilters.Add(filter);
// It is also required to set appropriate singulation control not to
// get tags with inventoried flag B for session 1
Now that the pre-filters are set (i.e. Tags are classified into matching or non-matching criteria), the Application needs to specify which tags should participate in the Inventory using rfid3.Config.Antennas[1].SetSingulationControl(). Singulation Control must be specified with respect to each Antenna like Pre-Filters.
// Set the singulation control
Antennas.SingulationControl s1_singulationControl = new Antennas.SingulationControl()
s1_singulationControl.Session = SESSION.SESSION_S1; // Set session to operate on S1. If not specified, reader uses its own way of implementing the state-unware singulation
rfid3.Config.Antennas[3].SetSingulationControl(s1_singulationControl);
// Set the singulation control
Antennas.SingulationControl s1_singulationControl = new Antennas.SingulationControl()
s1_singulationControl.Session = SESSION.SESSION_S1;
s1_singulationControl.Action.InventoryState = INVENTORY_STATE.INVENTORY_STATE_B;
s1_singulationControl.Action.SLFlag = SL_FLAG.SL_FLAG_DEASSERTED;
s1_singulationControl.Action.PerformStateAwareSingulationAction = true;
rfid3.Config.Antennas[3].SetSingulationControl(s1_singulationControl);
Inventory or Access operation when performed after setting pre-filters, will use the tags filtered out of pre-filters for their operation.
Triggers are the conditions that should be satisfied in order to start or stop an operation (Inventory or Access Sequence). This information can be specified using TriggerInfo class. The application can also configure the Tag-Report trigger which indicates when to receive n unique Tag-Reports from the Reader.
The following are some use-cases of using TRIGGER_INFO:
TriggerInfo triggerInfo = new TriggerInfo();
// start trigger GPI port 1 changes to true
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_GPI;
triggerInfo.StartTrigger.GPI.PortNumber = 1;
triggerInfo.StartTrigger.GPI.GPIEvent = true;
// stop trigger GPI port 1 changes to false
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_GPI_WITH_TIMEOUT;
triggerInfo.StopTrigger.GPI.PortNumber = 1;
triggerInfo.StopTrigger.GPI.GPIEvent = false;
triggerInfo.StopTrigger.GPI.TimeoutMilliseconds = 1000; // 1 sec
// report back each tag report as and when it is read by Reader
triggerInfo.TagReportTrigger = 1;
- Periodic Inventory Start inventory at a specified time for a specified duration repeatedly.
TriggerInfo triggerInfo = new TriggerInfo();
// start inventory on 12th of this month and 12am and runs 200 milliseconds of every 2 seconds
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_PERIODIC;
triggerInfo.StartTrigger.Periodic.PeriodMilliseconds = 2000; // perform inventory for 2 seconds
// start time
DateTime startTime = DateTime.UtcNow;
startTime.Day = 12;
startTime.Hour = 12;
triggerInfo.StartTrigger.Periodic.StartTime = startTime;
// stop trigger
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_DURATION;
triggerInfo.StopTrigger.Duration = 200; // stop after 200 milliseconds
// report back all read tags after completion of one round of inventory (i.e. one period)
triggerInfo.TagReportTrigger = 0;
TriggerInfo triggerInfo = new TriggerInfo();
// start inventory immediate
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;
// stop trigger
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;
triggerInfo.StopTrigger.NumAttempts.N = 3; // perform 3 rounds of inventory
triggerInfo.StopTrigger.NumAttempts.TimeoutMilliseconds = 3000; // timeout after 3 seconds
// report back all read tags after 3 rounds of inventory
triggerInfo.TagReportTrigger = 0;
TriggerInfo triggerInfo = new TriggerInfo();
// start inventory immediate
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;
// stop trigger
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_TAG_OBSERVATION_WITH_TIMEOUT;
triggerInfo.StopTrigger.TagObservation.N = 100; // stop inventory after reading 100 tags
triggerInfo.StopTrigger.NumAttempts.TimeoutMilliseconds = 3000; // timeout after 3 seconds
// report back all read tags after getting 100 unique tags or after 3 seconds
triggerInfo.TagReportTrigger = 0;
TriggerInfo triggerInfo = new TriggerInfo();
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_HANDHELD;
// Start Inventory when the Handheld trigger is pressed
triggerInfo.StartTrigger.Handheld.HandheldEvent = HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED;
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_HANDHELD_WITH_TIMEOUT;
// Stop Inventory when the Handheld trigger is released
triggerInfo.StopTrigger.Handheld.HandheldEvent = HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED;
triggerInfo.StopTrigger.Handheld.Timeout = 0;
rfid3.Actions.Inventory.Perform(null, triggerInfo, null);
TriggerInfo triggerInfo = new TriggerInfo();
// Tags will be periodically reported in every 10 seconds
triggerInfo.ReportTriggers.Period = 10;
There are various situations that act as conditions (triggers) for performing inventory.
Refer section Using Triggers to configure Triggers.
The following shows an example of performing 1 round of Inventory on Antennas 1 and 3.
TriggerInfo triggerInfo = new TriggerInfo();
// perform inventory on antenna 1 & 3
ushort[] antennaList = new ushort[2] { 1, 3 };
AntennaInfo antennaInfo = new AntennaInfo(antennaList);
// start inventory immediate
triggerInfo.StartTrigger.Type = START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE;
// stop trigger
triggerInfo.StopTrigger.Type = STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_N_ATTEMPTS_WITH_TIMEOUT;
triggerInfo.StopTrigger.NumAttempts.N = 1; // perform 1 round of inventory
triggerInfo.StopTrigger.NumAttempts.TimeoutMilliseconds = 0; // reader default timeout
// report back all read tags after 1 round of inventory
triggerInfo.TagReportTrigger = 0;
// perform inventory
rfid3.Actions.Inventory.Perform(null, triggerInfo, antennaInfo);
Post-filters are those filters which are applied on the Tags that the reader received through the pre-filters (if any).
Post-filters allow the application to set one or two tag patterns and to specify a condition as a combination of the patterns.
The following snippet shows setting a post-filter that does not get tags starting with 0x1122 and 0x2233.
PostFilter postFilter = new PostFilter();
byte[] tagMask = new byte[2] { 0xff, 0xff };
// Tag Pattern A
postFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;
postFilter.TagPatternA.TagPattern = new byte[2] { 0x11, 0x22 };
postFilter.TagPatternA.TagPatternBitCount = 2 * 8;
postFilter.TagPatternA.BitOffset = 0;
postFilter.TagPatternA.TagMask = tagMask;
postFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;
// Tag Pattern B
postFilter.TagPatternB.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;
postFilter.TagPatternB.TagPattern = new byte[2] { 0x22, 0x33 };
postFilter.TagPatternB.TagPatternBitCount = 2 * 8;
postFilter.TagPatternB.BitOffset = 32; //skip PC
postFilter.TagPatternB.TagMask = tagMask;
postFilter.TagPatternB.TagMaskBitCount = (uint)tagMask.Length * 8;
postFilter.MatchPattern = MATCH_PATTERN.NOTA_AND_NOTB;
// perform inventory with post filter
rfid3.Actions.Inventory.Perform(postFilter, null, null);
Starting from version
RFID_API3_5_1 onwards, applications can use RSSI based filtering if supported by the reader. This is indicated by the field IsRssiFilterSupported of ReaderCaps. The following code snippet does filtering of tags which have RSSI value in range -40 to -10.PostFilter
postFilter = new PostFilter();
postFilter.UseRSSIRangeFilter
= true;
postFilter.RssiRangeFilter.MatchRange
= MATCH_RANGE.WITHIN_RANGE;
postFilter.RssiRangeFilter.PeakRSSILowerLimit
= -40;
postFilter.RssiRangeFilter.PeakRSSIUpperLimit
= -10;
rfid3.Actions.Inventory.Perform(postFilter,
triggerInfo, null);
In order to perform an access operation on multiple tags, the Application can set ACCESS_FILTER to filter the required tags. If ACCESS_FILTER is not specified, the operation will be performed on all Tags. In any case, the PRE_FILTER(s) if any is set will apply prior to ACCESS_FILTER.
The following Access-filter gets all tags that have zeroed Reserved memory bank.
AccessFilter accessFilter = new AccessFilter();
byte[] tagMask = new byte[8] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
// Tag Pattern A
accessFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_RESERVED;
accessFilter.TagPatternA.TagPattern = new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
accessFilter.TagPatternA.TagPatternBitCount = 8 * 8;
accessFilter.TagPatternA.BitOffset = 0;
accessFilter.TagPatternA.TagMask = tagMask;
accessFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;
// Tag Pattern B
accessFilter.TagPatternB = null;
accessFilter.MatchPattern = MATCH_PATTERN.A;
Performing a single Access operation on multiple tags is an asynchronous operation. The function issues the access-operation and returns. The Reader performs one round of inventory using pre-filters if any, and then applies the access-filters and the resultant tags are subject to the access-operation. When the access operation is complete, the Dll signals the rfid3.Events.StatusNotify event with event data as ACCESS_STOP_EVENT. The Application can call the method rfid3.Actions.TagAccess.GetLastAccessResult to know the result. In case of Read access operation (rfid3.Actions.TagAccess.ReadEvent) the event rfid3.Events.ReadNotify is signalled when Tags are reported.
The following snippet shows a sample write-access operation:
// Create Event to signify access operation complete
AutoResetEvent AccessComplete;
AccessComplete = new AutoResetEvent(false);
rfid3.Events.NotifyAccessStartEvent = true;
rfid3.Events.NotifyAccessStopEvent = true;
rfid3.Events.StatusNotify += new Events.StatusNotifyHandler(Events_StatusNotify);
// Status Notification from the reader
public void Events_StatusNotify(object sender, Events.StatusEventArgs e)
{
switch (e.StatusEventData.StatusEventType)
{
case Events.STATUS_EVENT_TYPE.ACCESS_START_EVENT:
AccessComplete.Reset();
break;
case Events.STATUS_EVENT_TYPE.ACCESS_STOP_EVENT:
AccessComplete.Set();
break;
}
}
// Access Filter - EPC ID starting with 0x1122
AccessFilter accessFilter = new AccessFilter();
byte[] tagMask = new byte[2] { 0xff, 0xff };
// Tag Pattern A
accessFilter.TagPatternA.MemoryBank = MEMORY_BANK.MEMORY_BANK_EPC;
accessFilter.TagPatternA.TagPattern = new byte[2] { 0x11, 0x22};
accessFilter.TagPatternA.TagPatternBitCount = 2 * 8;
accessFilter.TagPatternA.BitOffset = 0;
accessFilter.TagPatternA.TagMask = tagMask;
accessFilter.TagPatternA.TagMaskBitCount = (uint)tagMask.Length * 8;
// Tag Pattern B
accessFilter.TagPatternB = null;
accessFilter.MatchPattern = MATCH_PATTERN.A;
// Write user memory bank data
TagAccess.WriteAccessParams writeParams = new TagAccess.WriteAccessParams();
byte[] writeData = new byte[4] { 0xff, 0xff, 0xff, 0xff };
writeParams.AccessPassword = 0;
writeParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;
writeParams.ByteOffset = 0;
writeParams.WriteDataLength = writeData.Length;
writeParams.WriteData = writeData;
// Asynchronous write operation
rfid3.Actions.TagAccess.WriteEvent(writeParams, accessFilter, null);
// wait for access operation to complete
AccessComplete.WaitOne();
uint successCount = 0;
uint failureCount = 0;
// Get Access operation results
rfid3.Actions.TagAccess.GetLastAccessResult(ref successCount, ref failureCount);
The Application can issue multiple access operations on a single go using Access-Sequence API. This is useful when each tag from a set of (access-filtered) tags is to be subject to an order of access operations.
The maximum number of access-operations that can be specified in an access sequence is specified in rfid3.ReaderCapabilites.MaxNumOperationsInAccessSequenceof ReaderCapabilities class.
The operations will be performed in the same order in which it is added to it sequence. An operation can be removed from the sequence using rfid3.Actions.TagAccess.OperationSequence.Delete and finally de-initialized if no more needed by calling the function rfid3.Actions.TagAccess.OperationSequence.DeleteAll().
// add Write Access operation - Write to User memory
TagAccess.OperationSequenceClass.Operation op1 = new TagAccess.OperationSequenceClass.Operation();
op1.AccessOperationCode = ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE;
op1.WriteAccessParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;
op1.WriteAccessParams.AccessPassword = 0;
op1.WriteAccessParams.ByteOffset = 0;
op1.WriteAccessParams.WriteData = new byte[4] { 0x55, 0x66, 0x77, 0x88 };
op2.WriteAccessParams.WriteDataLength = 4;
rfid3.Actions.TagAccess.OperationSequence.Add(op1);
// add Write Access operation - Write to Reserved memory bank
TagAccess.OperationSequenceClass.Operation op2 = new TagAccess.OperationSequenceClass.Operation();
op2.AccessOperationCode = ACCESS_OPERATION_CODE.ACCESS_OPERATION_WRITE;
op2.WriteAccessParams.MemoryBank = MEMORY_BANK.MEMORY_BANK_USER;
op2.WriteAccessParams.AccessPassword = 0;
op2.WriteAccessParams.ByteOffset = 0;
op2.WriteAccessParams.WriteData = new byte[4] { 0xBB, 0xBB, 0xBB, 0xBB };
op2.WriteAccessParams.WriteDataLength = 4;
rfid3.Actions.TagAccess.OperationSequence.Add(op1);
// perform access sequence
rfid3.Actions.TagAccess.OperationSequence.PerformSequence(null, null, null);
// wait for access operation complete
AccessComplete.WaitOne();
// get the access operation result
rfid3.Actions.TagAccess.GetLastAccessResult(ref successCount, ref failureCount);
// if the access operation is to be terminated without meeting stop trigger (if specified),
// stopSequence method can be called
rfid3.Actions.TagAccess.OperationSequence.StopSequence();